import { globalLayer, globalTool, customDataSource } from '../BQGIS-globalVar'
import fire from './fire2.gif'
import firePng from './fire2.png'
import smokeImg from "./smoke.png"


// 创建导弹
export function addGuidedMissile({ position, start = null, stop = null, id = null, name = null, pathStyle = {} }) {
    const option = {
        id,
        name,
        //Set the entity availability to the same interval as the simulation time.
        availability: new Cesium.TimeIntervalCollection([
            new Cesium.TimeInterval({
                start: start,
                stop: stop,
            }),
        ]),
        description: '导弹',

        //Use our computed positions
        position: position,

        //Automatically compute orientation based on position movement.
        orientation: new Cesium.VelocityOrientationProperty(position),

        //Load the Cesium plane model to represent the entity
        model: {
            uri: "/static/ceisumModel/guidedMissile.gltf",
            sizeInMeters: true,
            // scaleByDistance: new Cesium.NearFarScalar(200, 1, 8000, 0),
            minimumPixelSize: 32,
            maximumScale: 64,
            scale: 1,
        },

        //Show the path as a pink line sampled in 1 second increments.
        path: {
            resolution: 1,
            material: new Cesium.PolylineGlowMaterialProperty({
                glowPower: 0.1,
                color: Cesium.Color.YELLOW,
            }),
            width: 10,
        }
    }
    option.path = Object.assign(option.path, pathStyle)
    const entity = customDataSource.animationSource.entities.add(option);
    return entity
}

// 创建坦克
export function addTank({ position, start = null, stop = null, id = null, name = null, pathStyle = {} }) {
    const option = {
        id,
        name,
        //Set the entity availability to the same interval as the simulation time.
        availability: new Cesium.TimeIntervalCollection([
            new Cesium.TimeInterval({
                start: start,
                stop: stop,
            }),
        ]),
        description: '坦克',

        //Use our computed positions
        position: position,

        //Automatically compute orientation based on position movement.
        orientation: new Cesium.VelocityOrientationProperty(position),

        //Load the Cesium plane model to represent the entity
        model: {
            uri: "/static/ceisumModel/tank.gltf",
            sizeInMeters: true,
            // scaleByDistance: new Cesium.NearFarScalar(200, 1, 8000, 0),
            minimumPixelSize: 32,
            maximumScale: 64,
            scale: 1,
        },

        //Show the path as a pink line sampled in 1 second increments.
        path: {
            resolution: 1,
            material: new Cesium.PolylineGlowMaterialProperty({
                glowPower: 0.1,
                color: Cesium.Color.YELLOW,
            }),
            width: 10,
        },
    }
    option.path = Object.assign(option.path, pathStyle)
    const entity = customDataSource.animationSource.entities.add(option);
    return entity
}

export function addExplosion(position) {
    initAnimationLayer()
    return {
        fire: globalLayer.animationLayer.addGraphic(new mars3d.graphic.ParticleSystem({
            position, // 位置
            style: {
                image: firePng,
                particleSize: 2, // 粒子大小（单位：像素）
                emissionRate: 5, // 发射速率 （单位：次/秒）
                maxHeight: 5000, // 超出该高度后不显示粒子效果
                sizeInMeters: true,
                startColor: new Cesium.Color(1, 1, 1, 1), // 开始颜色
                endColor: new Cesium.Color(0.5, 0, 0, 0), // 结束颜色
                startScale: 3.0, // 开始比例（单位：相对于imageSize大小的倍数）
                endScale: 1.5, // 结束比例（单位：相对于imageSize大小的倍数）
                minimumSpeed: 5.0, // 最小速度（单位：米/秒）
                maximumSpeed: 7.0, // 最大速度（单位：米/秒）
            },
            attr: { remark: "火焰粒子效果" }
        })),
        blast: globalLayer.animationLayer.addGraphic(new mars3d.graphic.ParticleSystem({
            position, // 位置
            style: {
                image: smokeImg,
                lifetime: 1,
                loop: false,
                particleSize: 8, // 粒子大小（单位：像素）
                emissionRate: 15, // 发射速率 （单位：次/秒）
                maxHeight: 5000, // 超出该高度后不显示粒子效果
                sizeInMeters: true,
                // emitter: new Cesium.SphereEmitter(0.5),
                emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(90)),
                startColor: new Cesium.Color(1, 1, 1, 1), // 开始颜色
                endColor: new Cesium.Color(0.5, 0, 0, 0), // 结束颜色
                startScale: 3.0, // 开始比例（单位：相对于imageSize大小的倍数）
                endScale: 1.5, // 结束比例（单位：相对于imageSize大小的倍数）
                minimumSpeed: 7.0, // 最小速度（单位：米/秒）
                maximumSpeed: 9.0, // 最大速度（单位：米/秒）
            },
            attr: { remark: "爆炸冲击效果" }
        }))
    }
}

export function removeParticleSystem(particleSystem) {
    globalLayer.animationLayer.removeGraphic(particleSystem)
}

export function getClampToGroundPositionByPath(paths, interpolationAlgorithm, interpolationDegree, interval) {
    const {
        position, julianStartDate, julianStopDate
    } = getPositionByPath(paths, interpolationAlgorithm, interpolationDegree)
    return getClampToGroundPositionByPosition(position, julianStartDate, julianStopDate, interval)
}

export function getClampToGroundPositionByPosition(position, julianStartDate, julianStopDate, interval) {
    const timeArr = []
    const positions = []
    for (let time = julianStartDate; Cesium.JulianDate.compare(time, julianStopDate) < 0; time = Cesium.JulianDate.addSeconds(time, interval, new Cesium.JulianDate())) {
        timeArr.push(time)
        positions.push(Cesium.Cartographic.fromCartesian(position.getValue(time)))
    }
    return Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, positions).then(updatedPositions => {
        const newPath = []
        for (let i = 0; i < updatedPositions.length; i++) {
            newPath.push({
                time: Cesium.JulianDate.toDate(timeArr[i]),
                position: getLngLatArrByCartographic(updatedPositions[i])
            })
        }
        const result = getPositionByPath(newPath, position.interpolationAlgorithm, position.interpolationDegree)
        result.newPath = newPath
        return result
    })
}

export function getPositionByPath(paths, interpolationAlgorithm, interpolationDegree) {
    const position = new Cesium.SampledPositionProperty()
    position.setInterpolationOptions({
        interpolationAlgorithm: Cesium[interpolationAlgorithm],
    });
    position.setInterpolationOptions({
        interpolationDegree,
    });
    paths.forEach((item) => {
        position.addSample(
            Cesium.JulianDate.fromDate(new Date(item.time)),
            Cesium.Cartesian3.fromDegrees(...item.position)
        );
    });
    const start = new Date(paths[0].time);
    const stop = new Date(paths[paths.length - 1].time);
    const julianStartDate = Cesium.JulianDate.fromDate(start)
    const julianStopDate = Cesium.JulianDate.fromDate(stop)
    return {
        position, start, stop, julianStartDate, julianStopDate
    }
}

function getLngLatArrByCartographic(cartographic) {
    const lng = Cesium.Math.toDegrees(cartographic.longitude)
    const lat = Cesium.Math.toDegrees(cartographic.latitude)
    return [lng, lat, cartographic.height]
}


export function collisionDetection(entity, time) {
    const matrix4 = entity.computeModelMatrix(time, new Cesium.Matrix4());
    if (!matrix4) return
    let p1 = new Cesium.Cartesian3()
    Cesium.Matrix4.multiplyByPoint(matrix4, new Cesium.Cartesian3(4, 0, 0), p1)
    // const p1 = entity.position.getValue(time)
    let p2 = new Cesium.Cartesian3()
    Cesium.Matrix4.multiplyByPoint(matrix4, new Cesium.Cartesian3(7, 0, 0), p2)
    const ray = new Cesium.Ray(p1, p2)
    const feature = viewer.scene.pickFromRay(ray);
    return {
        entity: feature && feature.object && feature.object.id,
        position: feature && feature.position
    }
}

// export function initFireGif() {
//     return new Promise(resolve => {
//         const image = new Image();
//         let gifDiv = document.createElement('div')
//         gifDiv.appendChild(image)
//         image.setAttribute('rel:animated_src', fire)
//         image.setAttribute('rel:auto_play', '1')
//         fireGif = new SuperGif({ gif: image });
//         fireGif.load(function () {
//             resolve(fireGif)
//         })
//     });
// }

// export function addFire({ position, id = null, name = null }) {
//     return customDataSource.animationSource.entities.add({
//         id,
//         name,
//         position,
//         billboard: {
//             image: new Cesium.CallbackProperty(() => {
//                 return fireGif.get_canvas().toDataURL("image/png");
//             }, false),
//             // scaleByDistance: new Cesium.NearFarScalar(1.5e2, 0.3, 1.5e7, 0.07),
//             sizeInMeters: true,
//             verticalOrigin: Cesium.VerticalOrigin.Center,
//             heightReference: Cesium.HeightReference.NONE,
//         }
//     });
// }

export function addFire({ position, id = null, name = null }) {
    return new Promise(resolve => {
        const image = new Image();
        let gifDiv = document.createElement('div')
        gifDiv.appendChild(image)
        image.setAttribute('rel:animated_src', fire)
        image.setAttribute('rel:auto_play', '1')
        const superGif = new SuperGif({ gif: image });
        superGif.load(function () {
            const entity = customDataSource.animationSource.entities.add({
                id,
                name,
                position,
                billboard: {
                    image: new Cesium.CallbackProperty(() => {
                        return superGif.get_canvas().toDataURL("image/png");
                    }, false),
                    scaleByDistance: new Cesium.NearFarScalar(1.5e2, 0.3, 1.5e7, 0.07),
                    verticalOrigin: Cesium.VerticalOrigin.Center,
                    heightReference: Cesium.HeightReference.NONE,
                }
            });
            resolve(entity)
        })
    });
}

export function drawPoint() {
    initAnimationLayer()
    return globalLayer.animationLayer.startDraw({
        type: "point",
        style: {
            color: "#00ffff",
            pixelSize: 6,
            outlineColor: "#ffffff",
            outlineWidth: 2,
        },
    });
}

export function addPoint({ position, time }) {
    initAnimationLayer()
    const date = new Date(time)
    const graphic = new mars3d.graphic.PointEntity({
        position,
        attr: {
            time: date.getTime()
        },
        style: {
            color: "#00ffff",
            pixelSize: 6,
            outlineColor: "#ffffff",
            outlineWidth: 2,
            label: {
                font: "12px sans-serif",
                color: "00ffff",
                text: dateFormat(date),
                pixelOffsetY: -13,
                disableDepthTestDistance: 5000,
            }
        }
    })
    globalLayer.animationLayer.addGraphic(graphic)
    return graphic
}

export function initAnimationLayer() {
    if (!globalLayer.animationLayer) {
        globalLayer.animationLayer = new mars3d.layer.GraphicLayer()
        viewer.addLayer(globalLayer.animationLayer)
        bindLayerContextMenu(globalLayer.animationLayer)
    }
}

export function destroyAnimationLayer() {
    if (globalLayer.animationLayer) {
        globalLayer.animationLayer.remove(true)
        globalLayer.animationLayer = null
    }
}

export function initAnimationSource() {
    if (!customDataSource.animationSource) {
        customDataSource.animationSource = new Cesium.CustomDataSource("animationSource");
        viewer.dataSources.add(customDataSource.animationSource);
    }
}

export function destroyAnimationSource() {
    if (customDataSource.animationSource) {
        viewer.dataSources.remove(customDataSource.animationSource, true)
        customDataSource.animationSource = null
    }
}

export function removeAnimationEntities(entity) {
    customDataSource.animationSource.entities.remove(entity)
}

export function getAnimationSourceValues() {
    if (customDataSource.animationSource) {
        return customDataSource.animationSource.entities.values
    } else {
        return []
    }
}

export function getEntityById(id) {
    return customDataSource.animationSource.entities.getById(id)
}

export function clearLayer() {
    if (globalLayer.animationLayer) {
        globalLayer.animationLayer.clear(true)
    }
}

// 获取日期字符串
// 入参 fmt-格式 date-日期
export function dateFormat(date = new Date(), fmt = "YYYY-mm-dd HH:MM:SS") {
    let ret;
    const opt = {
        "Y+": date.getFullYear().toString(), // 年
        "m+": (date.getMonth() + 1).toString(), // 月
        "d+": date.getDate().toString(), // 日
        "H+": date.getHours().toString(), // 时
        "M+": date.getMinutes().toString(), // 分
        "S+": date.getSeconds().toString() // 秒
    };
    for (let k in opt) {
        ret = new RegExp("(" + k + ")").exec(fmt);
        if (ret) {
            fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
        };
    };
    return fmt;
}

export function getGeoJson() {
    return globalLayer.animationLayer.toGeoJSON()
}

export function loadGeoJSON(geojson) {
    globalLayer.animationLayer.loadGeoJSON(geojson)
}


export function download(content, filename) {
    const element = document.createElement('a');
    element.setAttribute('download', filename);
    element.style.display = 'none';
    // 字符内容转变成blob地址
    var blob = new Blob([JSON.stringify(content)]);
    element.href = URL.createObjectURL(blob);
    // 触发点击
    document.body.appendChild(element);
    element.click();
    // 然后移除
    document.body.removeChild(element);
};

export function getFileByJson(jsonString, fileName) {
    if (!jsonString) return
    const content = typeof jsonString == 'string' ? jsonString : JSON.stringify(jsonString)
    var blob = new Blob([content], {
        type: 'application/json'
    });
    let file = new File([blob], fileName, {
        type: 'application/json'
    })
    return file
}

export function bindLayerContextMenu(graphicLayer) {
    if (!globalTool.eventTarget) {
        globalTool.eventTarget = new mars3d.BaseClass() // viewer 自定义事件实例
    }
    graphicLayer.bindContextMenu([
        {
            text: "编辑路径点",
            icon: "fa fa-trash-o",
            show: (event) => {
                const graphic = event.graphic
                return graphic && graphic.type === "point"
            },
            callback: (e) => {
                const graphic = e.graphic
                if (!graphic) {
                    return
                }
                globalTool.eventTarget.fire("editTargetPoint", e)
            }
        },
        {
            text: "删除路径点",
            icon: "fa fa-trash-o",
            show: (event) => {
                const graphic = event.graphic
                return graphic && !graphic.isDestroy && graphic.type === "point"
            },
            callback: (e) => {
                const graphic = e.graphic
                if (!graphic) {
                    return
                }
                globalTool.eventTarget.fire("delTargetPoint", e)
                // const parent = graphic.parent // 右击是编辑点时
                // graphicLayer.removeGraphic(graphic)
                // if (parent) {
                //     graphicLayer.removeGraphic(parent)
                // }
            }
        },
        // {
        //     text: "此处播放爆炸动画",
        //     icon: "fa fa-trash-o",
        //     show: (event) => {
        //         return event.graphic && event.graphic.type === "point"
        //     },
        //     callback: (e) => {
        //         const graphic = e.graphic
        //         if (!graphic) {
        //             return
        //         }
        //         globalTool.eventTarget.fire("createFire", e)
        //     }
        // }
    ])
}